package com.yuelan.codelib.utils.pay;

import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.widget.Toast;

import com.alipay.sdk.app.PayTask;
import com.exmaple.baidumv.thread.BaseHttpThread;
import com.tencent.mm.sdk.modelpay.PayReq;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.WXAPIFactory;
import com.yuelan.codelib.utils.HttpConnent;
import com.yuelan.codelib.utils.LOG;
import com.yuelan.codelib.utils.MyHashMap;
import com.yuelan.codelib.utils.NetWorkUtil;
import com.yuelan.codelib.utils.PhoneUtil;
import com.yuelan.codelib.utils.TextUtil;
import com.yuelan.codelib.utils.VersionUtil;
import com.yuelan.codelib.utils.encryption.MD5Encoder;

public class PayUtil {
	public static final String ERROR_MESSAGE = "网络连接失败，请稍后重试";
	public static final String WX_APP_ID = "wx1adc05354c6ce944";
	public static final String WX_API_KEY = "6B4282F8F3F88A3247B502AD2B37C48F";

	public static void dopay(Activity context, PayInfo info,
			PayListener payListener) {
		new PayUtil(context, info, payListener).getOrderInfo();
	}

	public static final int payResultCode_Success = 0;// 支付成功
	public static final int payResultCode_Ing = -1;// 支付结果确认中
	public static final int payResultCode_Fail = -2;// 支付失败

	public interface PayListener {
		// 目前只有支付宝有返回，微信支付需要在onResume的地方自己做刷新币的处理
		public void payResult(int code);
	}

	Activity context;
	PayInfo payInfo;
	PayListener payListener;

	private PayReq req = new PayReq();

	public PayUtil(Activity context, PayInfo info, PayListener payListener) {
		this.context = context;
		this.payInfo = info;
		this.payListener = payListener;
	}

	public synchronized static String getNowDay() {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHH");
		Date curDate = new Date(System.currentTimeMillis());// 获取当前时间
		return formatter.format(curDate);
	}

	public void getOrderInfo() {
		Map<String, String> maps = new MyHashMap<String, String>();
		maps.put("userName", payInfo.userName); // 用户id或者用户名
		maps.put("orderChannel", "" + payInfo.orderChannel); //
		maps.put("price", "" + payInfo.price); // 价格（200.13）2位小数
		maps.put("orderMark", payInfo.info); // 订单备注
		maps.put("orderType", payInfo.orderType + ""); // 1猫咪直播2,咪咪宝贝
		maps.put("costType", "1"); // 1充值金币
		maps.put("orderBody", payInfo.showInfo); // 订单信息（充值100金币）
		maps.put("phoneNum", ""); // 用户手机号
		maps.put("imei", PhoneUtil.getIMEI(context)); // 用户imei
		maps.put("androidId", PhoneUtil.getDeviceId(context)); // 用户的安卓id
		maps.put("vendor", "" + PhoneUtil.getMobileManufacturer()); // 用户的手机厂商(小米
																	// 华为等等)
		maps.put("models", "" + PhoneUtil.getDeviceType()); // 用户的手机机型（小米note）
		maps.put("osName", "android"); // 用户是系统名称（ios android yunos 等等）
		maps.put("osVersion", PhoneUtil.getAndroidVersion()); // 户的系统版本（安卓4.0
																// 5.0等等）
		maps.put("networkType", NetWorkUtil.getNetWork(context)); // 用户的网络状态（Wifi
																	// 3g 4g wap
																	// 等等）
		maps.put("appversionName", VersionUtil.getVerName(context)); // app的版本名称
		maps.put("appversionCode", "" + VersionUtil.getVerCode(context)); // app的版本号
		maps.put(
				"sign",
				MD5Encoder.EncoderByMd5(maps.get("userName")
						+ maps.get("orderChannel") + maps.get("price")
						+ maps.get("orderType") + maps.get("costType")
						+ maps.get("orderBody") + "MaoMiLive" + getNowDay())); // 签名

		new Thread(new GetOrderInfoThread(handler_getOrderInfo, maps, context))
				.start();
	}

	private Handler handler_getOrderInfo = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case BaseHttpThread.PostSuccess:
				String json = (String) msg.obj;
				LOG.v(json);
				try {
					JSONObject obj = new JSONObject(json);
					if (obj != null) {
						if (obj.getString("resultCode").equals("200")) {
							if (obj.getString("orderChannel").equals("1"))// 1支付宝
							{
								doAliPay(obj.getString("resultInfo"));
							} else if (obj.getString("orderChannel")
									.equals("2"))// 2微信
							{
								doWeiXinPay(obj.getString("resultInfo"));
							}
						} else {
							toast(obj.getString("resultInfo"));
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				break;
			case BaseHttpThread.PostFail:
				toast(ERROR_MESSAGE);
				break;
			default:
				break;
			}
		};
	};

	private void doAliPay(final String payInfo) {
		LOG.v("tongji_handler_info 1 result : " + payInfo);
		Runnable payRunnable = new Runnable() {
			@Override
			public void run() {
				// 构造PayTask 对象
				PayTask alipay = new PayTask(context);
				// 调用支付接口
				String result = alipay.pay(payInfo);
				LOG.v("tongji_handler_info 2 result : " + result);
				Message msg = new Message();
				msg.what = 1;
				msg.obj = result;
				mHandler.sendMessage(msg);
			}
		};
		Thread payThread = new Thread(payRunnable);
		payThread.start();
	}

	private Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 1: {
				String result = (String) msg.obj;
				Result resultObj = new Result(result);
				String resultStatus = resultObj.resultStatus;

				// 判断resultStatus 为“9000”则代表支付成功，具体状态码代表含义可参考接口文档
				if (TextUtils.equals(resultStatus, "9000")) {
					if (payListener != null)
						payListener.payResult(payResultCode_Success);
					toast("支付成功");
				} else {
					// 判断resultStatus 为非“9000”则代表可能支付失败
					// “8000”
					// 代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认，最终交易是否成功以服务端异步通知为准（小概率状态）
					if (TextUtils.equals(resultStatus, "8000")) {
						if (payListener != null)
							payListener.payResult(payResultCode_Ing);
//						toast("支付结果确认中");
					} else {
						if (payListener != null)
							payListener.payResult(payResultCode_Fail);
//						toast("支付失败");
					}
				}
			}
				break;
			default:
				break;
			}
		};
	};

	public static String doWeiXinPayGetParam(String payInfo, String key) {
		String[] locations;

		locations = MatcherHelper(
				String.format("<%s><!\\[CDATA\\[[^\\]]*\\]\\]></%s>", key, key),
				payInfo);
		if (locations.length == 1) {
			locations = MatcherHelper(
					String.format("<!\\[CDATA\\[[^\\]]*\\]\\]>", key, key),
					locations[0]);
			if (locations.length == 1) {
				String valueStr = locations[0];
				String strStart = "<![CDATA[";
				String strEnd = "]]>";
				return valueStr.substring(strStart.length(), valueStr.length()
						- strEnd.length());
			}
		}
		return null;
	}

	private String genNonceStr() {
		Random random = new Random();
		return MD5Encoder.EncoderByMd5(String.valueOf(random.nextInt(10000)));
	}

	private long genTimeStamp() {
		return System.currentTimeMillis() / 1000;
	}

	private String genAppSign(List<NameValuePair> params) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < params.size(); i++) {
			sb.append(params.get(i).getName());
			sb.append('=');
			sb.append(params.get(i).getValue());
			sb.append('&');
		}
		sb.append("key=");
		sb.append(WX_API_KEY);
		String appSign = MD5Encoder.EncoderByMd5(sb.toString()).toUpperCase();
		// MyLog.e("orion", appSign);
		return appSign;
	}

	private void genPayReq() {
		req.packageValue = "Sign=WXPay";
		req.nonceStr = genNonceStr();
		req.timeStamp = String.valueOf(genTimeStamp());

		List<NameValuePair> signParams = new LinkedList<NameValuePair>();
		signParams.add(new BasicNameValuePair("appid", req.appId));
		signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
		signParams.add(new BasicNameValuePair("package", req.packageValue));
		signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
		signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
		signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));

		req.sign = genAppSign(signParams);

		// MyLog.e("orion", signParams.toString());
	}

	private void sendPayReq() {
		IWXAPI msgApi = WXAPIFactory.createWXAPI(context, null);
		msgApi.registerApp(WX_APP_ID);
		msgApi.sendReq(req);
	}

	private void doWeiXinPay(String payInfoEncode) {
		final String payInfo = URLDecoder.decode(payInfoEncode);
		LOG.v("result : " + payInfo);
		final String appid = doWeiXinPayGetParam(payInfo, "appid");
		final String mch_id = doWeiXinPayGetParam(payInfo, "mch_id");
		final String prepay_id = doWeiXinPayGetParam(payInfo, "prepay_id");
		if (appid == null || mch_id == null || prepay_id == null) {
			toast("支付失败");
			return;
		}
		// toast("开始支付");
		Runnable payRunnable = new Runnable() {
			@Override
			public void run() {
				LOG.v("appid : " + appid);
				LOG.v("mch_id : " + mch_id);
				LOG.v("prepay_id : " + prepay_id);
				req.appId = appid;
				req.partnerId = mch_id;
				req.prepayId = prepay_id;
				genPayReq();
				sendPayReq();
			}
		};
		Thread payThread = new Thread(payRunnable);
		payThread.start();
	}

	public class GetOrderInfoThread extends BaseHttpThread {
		private Context c;

		public GetOrderInfoThread(Handler handler, Map<String, String> maps,
				Context c) {
			super(handler, maps);
			this.c = c;
		}

		@Override
		public void run() {
			super.run();
			String url = payInfo.url;
			LOG.v("TongJiInfoThread" + getFullUrl(url, maps));
			String json = HttpConnent.doHttpPost(url, getPostParams(maps), 0);
			LOG.v("TongJiInfoThread" + "ret = " + json);
			if (handler != null) {
				if (TextUtil.notNull(json)) {
					try {
						Message msg = new Message();
						msg.what = PostSuccess;
						msg.obj = json;
						handler.sendMessage(msg);
						return;
					} catch (Exception e) {

					}
				}
				handler.sendEmptyMessage(PostFail);
			}
		}
	}

	public void toast(String text) {
		try {
			Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
		} catch (Exception e) {
		}
	}

	public static String[] MatcherHelper(String exp, String text) {
		List<String> list = new ArrayList<String>();
		Matcher m = Pattern.compile(exp).matcher(text);
		while (m.find()) {
			list.add(m.group());
		}
		return list.toArray(new String[list.size()]);
	}

}
